#include "modbus_poll.h"

MasterConfig master = {0};

/**
 * @brief Modbus主机初始化函数.
 * @param 
 *   - *master       主机配置结构体指针.
 *   - *port         端口配置结构体指针.
 *   - timeout_ms    响应超时时间(ms).
 *
 * @return void
 */
void ModbusMaterCreate(MasterConfig *master, ModbusMasterPort *port, uint32_t timeout_ms) 
{
    memcpy(&master->port, port, sizeof(ModbusMasterPort));
    master->state = MB_IDLE;
    master->timeout_ms = timeout_ms;
    master->rx_index = 0;
    master->last_error = MODBUS_EX_NONE;
}

/**
 * @brief 发送Modbus请求帧.
 * @param 
 *   - *master       主机配置结构体指针.
 *   - slave_addr    从机地址.
 *   - function      功能码.
 *   - *dat          请求数据缓冲区.
 *   - data_len      请求数据长度.
 *
 * @return void
 */
static void MasterSendRequest(MasterConfig *master, uint8_t slave_addr, uint8_t function, const uint8_t *dat, uint16_t data_len) 
{
    uint8_t frame[256];
    uint16_t index = 0;
    uint16_t crc = 0;
    // 构建帧头
    frame[index++] = slave_addr;
    frame[index++] = function;
    memcpy(&frame[index], dat, data_len);
    index += data_len;
    
    // 计算 CRC
    crc = modbus_crc16(frame, index);
    frame[index++] = crc & 0xFF;
    frame[index++] = (crc >> 8) & 0xFF;
    
    // 发送帧
    master->port.uart_send(frame, index);
    master->last_send_time = master->port.get_timestamp_ms();
    master->last_slave_addr = slave_addr;
    master->state = MB_WAITING_RESPONSE;
    master->rx_index = 0;
    
    // 设置期望响应长度
    if (function == 0x03) {
        // 读寄存器响应: 地址1 + 功能码1 + 字节数1 + 数据(N*2) + CRC2
        master->expected_length = 5 + data_len; // data_len 是寄存器数量 * 2
    } else if (function == 0x06) {
        // 写寄存器响应固定8字节
        master->expected_length = 8;
    }
}

/**
 * @brief 处理接收到的Modbus响应数据.
 * @param 
 *   - *master       主机配置结构体指针.
 *
 * @return ModbusException 处理结果异常码
 */
static ModbusException ProcessReceivedData(MasterConfig *master)
{
  
    // 检查最小帧长度
    if (master->rx_index < 5) return MODBUS_EX_NONE;
    
    // 验证地址匹配
    if (master->rx_buffer[0] != master->last_slave_addr) {
        return MODBUS_EX_SLAVE_FAILURE;
    }
   
    // 验证CRC   
    if (modbus_crc16(master->rx_buffer, master->rx_index) != 0) 
        return MODBUS_EX_SLAVE_FAILURE;
 
    // 检查异常响应
    if (master->rx_buffer[1] & 0x80) {
        return (ModbusException)master->rx_buffer[2];
    }

    return MODBUS_EX_NONE;
}
  
/**
 * @brief Modbus主机轮询处理函数.
 * @param 
 *   - *master       主机配置结构体指针.
 *   - *rx_queue     接收环形队列指针.
 *
 * @return ModbusException 异常码
 */
ModbusException MasterPoll(MasterConfig *master, RingBuffer_t *rx_queue) 
{
    uint32_t current_time = master->port.get_timestamp_ms();
    uint8_t xdata temp_buf[64];
    uint16_t bytes_read = 0;
    uint16_t i = 0; 
    ModbusException ex = MODBUS_EX_NONE;
    // 1. 处理超时
    if (master->state == MB_WAITING_RESPONSE && 
        (current_time - master->last_send_time) > master->timeout_ms) {
        master->state = MB_TIMEOUT;
        return MODBUS_EX_SLAVE_FAILURE;
    }    

    // 2. 从队列读取数据
    if(!QueueIsEmpty(rx_queue))
        bytes_read = Queue_PopAll(rx_queue, temp_buf);
    else return MODBUS_EX_SLAVE_FAILURE;

    for (i = 0; i < bytes_read; i++) {
        if (master->rx_index < sizeof(master->rx_buffer)) 
            master->rx_buffer[master->rx_index++] = temp_buf[i];
        else {
            // 缓冲区溢出
            master->state = MB_TIMEOUT;
            master->last_error = MODBUS_EX_ILLEGAL_VALUE;
            break;
        }
    }    
    // 3. 检查是否收到完整响应
    if (master->state == MB_WAITING_RESPONSE && 
        master->rx_index >= master->expected_length) 
    {
        ex = ProcessReceivedData(master);
        if (ex == MODBUS_EX_NONE) 
        {
            master->state = MB_RESPONSE_RECEIVED;
        }
        else 
            master->last_error = ex;
        
            
        
    }    
    // 4. 返回当前状态对应的错误码
    if (master->state == MB_TIMEOUT) 
        return master->last_error;
    
    return MODBUS_EX_NONE;
}

/**
 * @brief 读取保持寄存器请求.
 * @param 
 *   - *master       主机配置结构体指针.
 *   - slave_addr    从机地址.
 *   - start_addr    起始寄存器地址.
 *   - reg_count     寄存器数量.
 *
 * @return ModbusException 异常码
 */
ModbusException MasterReadRegisters(MasterConfig *master, uint8_t slave_addr, uint16_t start_addr, uint16_t reg_count) 
{
    uint8_t xdata req[4];
    // 只在空闲状态接受新请求
    if (master->state != MB_IDLE) {
        return MODBUS_EX_SLAVE_FAILURE;
    }
    master->state = MB_WAITING_RESPONSE; 
    // 构建请求
    req[0] = (start_addr >> 8) & 0xFF;
    req[1] = start_addr & 0xFF;
    req[2] = (reg_count >> 8) & 0xFF;
    req[3] = reg_count & 0xFF;
  
    // 发送请求
    MasterSendRequest(master, slave_addr, 0x03, req, sizeof(req));
    return MODBUS_EX_NONE;
}

/**
 * @brief 写入单个寄存器请求.
 * @param 
 *   - *master       主机配置结构体指针.
 *   - slave_addr    从机地址.
 *   - reg_addr      寄存器地址.
 *   - value         写入值.
 *
 * @return ModbusException 异常码
 */
ModbusException MasterWriteRegister(MasterConfig *master, uint8_t slave_addr, uint16_t reg_addr, uint16_t value) {
    uint8_t xdata req[4];
    // 只在空闲状态接受新请求
    if (master->state != MB_IDLE) {
        return MODBUS_EX_SLAVE_FAILURE;
    }
    
    // 构建请求   
    req[0] = (reg_addr >> 8) & 0xFF;
    req[1] = reg_addr & 0xFF;
    req[2] = (value >> 8) & 0xFF;
    req[3] = value & 0xFF;
    
    // 发送请求
    MasterSendRequest(master, slave_addr, 0x06, req, sizeof(req));
    return MODBUS_EX_NONE;
}

/**
 * @brief 获取读取寄存器结果.
 * @param 
 *   - *master       主机配置结构体指针.
 *   - *output       输出缓冲区.
 *   - reg_count     寄存器数量.
 *
 * @return ModbusException 异常码
 */
ModbusException MasterGetReadResult(MasterConfig *master, uint16_t *output, uint16_t reg_count) 
{
    uint8_t byte_count = 0;
    uint16_t i = 0;
    if (master->state != MB_RESPONSE_RECEIVED)
        return MODBUS_EX_SLAVE_FAILURE;
    
    // 解析寄存器数据
    byte_count = master->rx_buffer[2];
    if (byte_count != reg_count * 2) {
        return MODBUS_EX_ILLEGAL_VALUE;
    }
    
    for (i = 0; i < reg_count; i++) {
        output[i] = (master->rx_buffer[3 + 2*i] << 8) | 
                     master->rx_buffer[4 + 2*i];
    }
    
    // 重置状态
    master->state = MB_IDLE;
    return MODBUS_EX_NONE;
}

/**
 * @brief 获取写入寄存器结果.
 * @param 
 *   - *master       主机配置结构体指针.
 *
 * @return ModbusException 异常码
 */
ModbusException MasterGetWriteResult(MasterConfig *master) 
{
    if (master->state != MB_RESPONSE_RECEIVED) 
        return MODBUS_EX_SLAVE_FAILURE;       
    // 验证响应长度
    if (master->rx_index != 8) 
        return MODBUS_EX_ILLEGAL_VALUE;   
    // 重置状态
    master->state = MB_IDLE;
    return MODBUS_EX_NONE;
}
